package com.cskaoyan.javase.oop2._2polymorphic._2advantage;


/**
 * 多态是面向对象三大特征之一，它基于继承而实现，是面向对象思想的集大成者。
 * 接下来我们研究一下，它的优缺点。我们通过一个案例：
 *
 * 科学家要收集动物的叫声去研究，先要收集猫，狗两种动物的叫声研究。
 * 随后又扩展到其它动物，最后又需要研究人类。
 *
 * 从这个案例，我们其实就可以大致总结多态的优点了：
 *      1.要实现多态必须要继承，而继承提高了代码复用率，提升了程序的可维护性。（继承保证）
 *      2.有了多态后，用父类引用指向不同子类对象
 *          只需要调用同名方法，就能自动根据不同子类对象，得出不同的行为。
 *          这大幅度简化了代码，提升了程序的扩展性。（多态保证）
 *
 * 缺点：父类引用会限制子类对象的功能，父类引用无法使用子类独有成员。
 *
 * 如何解决上述问题呢？
 * 只要将父类引用向下转型变成子类引用，这样就能恢复子类对象的功能
 * 这个过程，向下转型，是引用数据类型的强制类型转换
 *
 * @since 14:31
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // collectCatVoice(new Cat());
        // collectCatVoice(new Dog());
        collectAnimalVoice(new Dog());
        collectAnimalVoice(new Cat());
        collectAnimalVoice(new Pig());
        collectAnimalVoice(new Person());
    }

    // 收集猫的叫声然后研究
    /*public static void collectCatVoice(Cat c){
        // 抓一只🐱过来，让它叫
        c.shout();
        // 收集研究叫声
    }*/

    // 收集动物的叫声然后研究
    public static void collectAnimalVoice(Animal a) {
        // 搞一只动物过来，让它叫
        if (a instanceof Person){
            // 说明对象是Person对象或者Person的子类对象，总之可以强转成Person引用
            // 如果是人类需要加钱，然后叫
            Person p = (Person) a;
            p.addMoney();
        }
        a.shout();
        // 收集研究叫声
    }

}

class Animal {
    public void shout() {
        System.out.println("动物发出了叫声~~");
    }
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵喵~~");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("汪汪汪~~");
    }
}

class Pig extends Animal {
    @Override
    public void shout() {
        System.out.println("小猪佩奇一样的叫声~");
    }
}

class Person extends Animal {
    @Override
    public void shout() {
        System.out.println("嘤嘤嘤~");
    }

    // 要想人类配合研究，需要加钱，所以人类具有特殊的行为：加钱
    public void addMoney() {
        System.out.println("加钱钱都好说，不给钱这个干不了~~");
    }
}